package com.yangjiangtao.reflect.ioc;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
//解析 XML 配置文件，创建 Bean 实例，并完成依赖注入
public class MyApplicationContext {
    private Map<String, Object> beans = new HashMap<>();

    public MyApplicationContext(String xmlPath) throws Exception {
        // 解析XML配置文件
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(xmlPath);

        // 获取bean的定义
        NodeList beanNodes = doc.getElementsByTagName("bean");//获取所有bean节点
        for (int i = 0; i < beanNodes.getLength(); i++) {
            Element beanNode = (Element) beanNodes.item(i);//获取一个bean节点
            String id = beanNode.getAttribute("id");//获取bean的id
            String className = beanNode.getAttribute("class");//获取bean的class，class是bean的全限定名

            // 创建bean的实例
            Class<?> beanClass = Class.forName(className);
            Object beanInstance = beanClass.newInstance();

            // 将bean的实例添加到beans中
            beans.put(id, beanInstance);
        }

        // 完成依赖注入
        for (int i = 0; i < beanNodes.getLength(); i++) {
            Element beanNode = (Element) beanNodes.item(i);//获取一个bean节点
            String id = beanNode.getAttribute("id");//
            Object beanInstance = beans.get(id);//获取bean的实例

            NodeList propertyNodes = beanNode.getElementsByTagName("property");//获取bean节点下的所有property节点
            for (int j = 0; j < propertyNodes.getLength(); j++) {//遍历property节点
                Element propertyNode = (Element) propertyNodes.item(j);//获取一个property节点
                String name = propertyNode.getAttribute("name");//获取property的name属性
                String ref = propertyNode.getAttribute("ref");//获取property的ref属性

                // 获取setter方法
                Method setterMethod = beanInstance.getClass().getMethod("set" + name.substring(0, 1).toUpperCase() + name.substring(1), GeLi.class);
                // 调用setter方法
                setterMethod.invoke(beanInstance, beans.get(ref));
            }
        }
    }

    public Object getBean(String id) {//获取bean
        return beans.get(id);
    }
}
